package bigdata.monitor.binlog.utils;

import bigdata.monitor.binlog.entity.MonitorRule;
import lombok.extern.slf4j.Slf4j;

/**
 * 将规则配置转换为 Doris 布尔表达式
 * 基础监控仅包含：
 * - TYPE: 类型校验（严格模式、宽松模式?）
 * - ENUM: 码值校验
 * - LENGTH: 长度校验
 */
@Slf4j
public class RuleConditionConverter {

    /**
     * 转换规则为 Doris 表达式
     */
    public static String toDorisExpression(MonitorRule rule) {
        if ("CUSTOM".equals(rule.getRuleType())) {
            return rule.getTriggerCondition();
        }

        // 基础规则：生成“通过条件”，然后外层加 NOT → 变成“违规条件”
        String dorisPassExpr = buildPassCondition(rule);
        return "NOT (" + dorisPassExpr + ")";
    }

    private static String buildPassCondition(MonitorRule rule) {
        String simple = rule.getSimpleCondition();
        if (simple == null || !simple.contains(":")) {
            throw new IllegalArgumentException("Invalid simple_condition for rule: " + rule.getRuleCode());
        }

        String[] parts = simple.split(":", 2);
        String field = parts[0].trim();
        String spec = parts[1].trim();
        String jsonPath = "$.after." + field; // 默认从 after 提取

        switch (rule.getRuleType()) {
            case "TYPE":
                return convertTypeCheck(jsonPath, spec);
//            case "RANGE":
//                return convertRangeCheck(jsonPath, spec);
            case "ENUM":
                return convertEnumCheck(jsonPath, spec);
            case "LENGTH":
                return convertLengthCheck(jsonPath, spec);
            default:
                throw new IllegalArgumentException("Unsupported rule_type: " + rule.getRuleType());
        }
    }

    private static String convertTypeCheck(String jsonPath, String typeSpec) {
        // 检查是否为宽松模式（以 ? 结尾）
        boolean isLenient = typeSpec.endsWith("?");
        String type = isLenient ? typeSpec.substring(0, typeSpec.length() - 1) : typeSpec;

        switch (type.toLowerCase()) {
            case "int":
            case "integer":
                if (isLenient) {
                    // 宽松整数：接受 JSON 数字 或 符合整数格式的字符串
                    return String.format(
                            "(" +
                                    "  get_json_bigint(data, '%s') IS NOT NULL" +          // 严格整数
                                    "  OR (" +
                                    "    get_json_string(data, '%s') IS NOT NULL" +        // 是字符串
                                    "    AND get_json_string(data, '%s') REGEXP '^-?(0|[1-9][0-9]*)$'" + // 且符合整数正则
                                    "  )" +
                                    ")",
                            jsonPath, jsonPath, jsonPath
                    );
                } else {
                    // 严格整数：仅接受 JSON 数字
                    return String.format("get_json_bigint(data, '%s') IS NOT NULL", jsonPath);
                }

            case "double":
            case "float":
                if (isLenient) {
                    // 宽松小数：接受 JSON 数字 或 符合小数格式的字符串
                    return String.format(
                            "(" +
                                    "  get_json_double(data, '%s') IS NOT NULL" +          // 严格小数
                                    "  OR (" +
                                    "    get_json_string(data, '%s') IS NOT NULL" +        // 是字符串
                                    "    AND get_json_string(data, '%s') REGEXP '^-?(0|[1-9][0-9]*)(\\\\.[0-9]+)?([eE][-+]?[0-9]+)?$'" + // 小数正则
                                    "  )" +
                                    ")",
                            jsonPath, jsonPath, jsonPath
                    );
                } else {
                    // 严格小数：仅接受 JSON 数字
                    return String.format("get_json_double(data, '%s') IS NOT NULL", jsonPath);
                }

            case "string":
                if (isLenient) {
                    throw new IllegalArgumentException("String type does not support lenient mode");
                }
                // 字符串校验：仅接受 JSON 字符串
                return String.format("get_json_string(data, '%s') IS NOT NULL", jsonPath);

            default:
                throw new IllegalArgumentException("Unsupported type: " + type);
        }
    }

    /**
     * SELECT CAST(json_unquote(get_json_string(data, '$.size')) AS DOUBLE ) BETWEEN 1 AND 1.2
     * FROM (
     *          SELECT json_parse('{"size": 1.2}') AS data
     *      ) t1;
     */
//    private String convertRangeCheck(String jsonPath, String rangeSpec) {
//        if (!rangeSpec.matches("^\\d+-\\d+$")) {
//            throw new IllegalArgumentException("Invalid range format: " + rangeSpec);
//        }
//        String[] bounds = rangeSpec.split("-");
//        int min = Integer.parseInt(bounds[0]);
//        int max = Integer.parseInt(bounds[1]);
//        return String.format(
//                "CAST(get_json_bigint(data, '%s') AS INT) BETWEEN %d AND %d",
//                jsonPath, min, max
//        );
//    }

    private static String convertEnumCheck(String jsonPath, String enumSpec) {
        String[] values = enumSpec.split(",");
        StringBuilder inClause = new StringBuilder("get_json_string(data, '");
        inClause.append(jsonPath).append("') IN (");
        for (int i = 0; i < values.length; i++) {
            if (i > 0) inClause.append(", ");
            inClause.append("'").append(values[i].trim()).append("'");
        }
        inClause.append(")");
        return inClause.toString();
    }

    private static String convertLengthCheck(String jsonPath, String lengthSpec) {
        int length = Integer.parseInt(lengthSpec);
        return String.format(
                "char_length(json_unquote(json_extract(data, '%s'))) = %d",
                jsonPath, length
        );
    }
}
